package auditoryUIbk;
import java.io.*;
import java.util.*;
import org.xml.sax.*;
//import java.awt.*;
//import java.awt.event.*;
import org.xml.sax.helpers.ParserFactory;
import auditoryTree.*;

//
// This class loads an XML JavaMenus file, and (after loading) returns
// menus by name.
//

public class SaxSunburstLoader extends HandlerBase{

	private Parser _parser;
	private final static String _parserClass = "org.apache.xerces.parsers.SAXParser";
	private Vector _treeStack;
	
	private TreeModel _defaultTreeModel;
	
	public SaxSunburstLoader() {
		createParser();
		_treeStack = new Vector();
		_defaultTreeModel = new TreeModel("TopModel");
	}

	/**
	 * Initialize the internal parser.
	 */
protected void createParser() {
	_parser = null;
	try {
		_parser = ParserFactory.makeParser(_parserClass);
	} catch (Exception ex) {
		G.debug("SaxMenuFactory.createParser: " + _parserClass + ": " + ex.getMessage());
		ex.printStackTrace();
	}
}

/**
 * Add a menu to the current menu
 */
protected void add(TreeModel model_) {
	TreeModel modelCurrent = modelCurrent();
	if (modelCurrent != null) {
		modelCurrent.addChild(model_);
	} 
}

	/**
	 * Define a menu, add it the the current menu, and then make
	 * the new menu the current menu.
	 */
protected void defineTreeModel(AttributeList attrs_) {
	String sModelName = attrs_.getValue("name");
	String sLabel = attrs_.getValue("label");
	String sFile = attrs_.getValue("file");
	
	if (sLabel == null) sLabel = sModelName;

	TreeModel model = new TreeModel(sModelName);
	if (sModelName != null) {
		//do i really need this?
		model.setTitle(sLabel);
		model.setName(sModelName);
		model.setSoundFile(sFile);
		
	} else {
		sModelName = model.getName();
		sLabel = model.getTitle();
	}
	G.debug("Created Tree Model " + sModelName);

	// Add to current context and make new menu the current menu to build
	//maybe I need to add this guy and push it into the stack
	add(model);
	pushModel(model);
}
	/**
	 * Report that the document parse is complete.
	 */
public void endDocument() {
	modelPop();
	G.debug("End document");
}
	/**
	 * Handle the end of an element context. This varies by element type.
	 */
public void endElement(String sName_) {
	// Every element pushes something, even if it's just its parent's handler

	
	if (sName_.equalsIgnoreCase("TreeModel")) {
		TreeModel modelCurrent = modelCurrent();
		if (modelCurrent != null) {
			G.debug("End treeModel " + modelCurrent.getTitle());
		} else {
			G.debug("End unnamed menu");
		}
		modelPop();
	}
	
}
	/**
	 * Load menus from a file
	 */
public void loadMenus(File file_) {
	try {
		Reader reader = new FileReader(file_);
		loadMenus(reader);
	} catch (FileNotFoundException ex) {
		G.debug("SaxMenuFactory.loadMenus: " + file_ + ": " + ex.getMessage());
	}
}
	/**
	 * Load menus from an input stream
	 */
public void loadMenus(InputStream istream_) {
	loadMenus(new InputStreamReader(istream_));
}
	/**
	 * Load menus from a "Reader"
	 */
public void loadMenus(Reader reader_) {
	if (_parser == null)
		return;
	_parser.setDocumentHandler(this);
	try {
		_parser.parse(new InputSource(reader_));
	} catch (SAXException ex) {
		G.debug("Parse error: " + ex.getMessage());
	} catch (Exception ex) {
		G.debug("SaxMenuFactory.loadMenus(): " + ex.getClass().getName() +
			ex.getMessage());
		ex.printStackTrace();
	}
}
	/**
	 * Load menus from a file
	 */
public void loadMenus(String sFilename_) {
	loadMenus(new File(sFilename_));
}
	
	/**
	 * Return reference to current menu
	 */
protected TreeModel modelCurrent() {
	int iStacksize = _treeStack.size();
	if (iStacksize == 0) {
		return null;
	}
	
	TreeModel modelToReturn = (TreeModel)_treeStack.elementAt(iStacksize - 1);
	return modelToReturn;
}

	/**
	 * Push menu onto menu stack
	 */
protected void pushModel(TreeModel model_) {
	_treeStack.addElement(model_);
}

	/**
	 * Pop menu from current menu stack.
	 */
protected TreeModel modelPop() {
	TreeModel modelToReturn = modelCurrent();
	if (modelToReturn != null) {
		_treeStack.removeElementAt(_treeStack.size() - 1);
	}
	return modelToReturn;
}

	/**
	 * Report that a document has begun
	 */
public void startDocument() {
	G.debug("Begin document");
	pushModel(_defaultTreeModel);
}
	/**
	 * Handler the beginning of an element.
	 */
public void startElement(String sName_, AttributeList attrs_) {

	// If "menu", then create a menu.
	if (sName_.equals("TreeModel")) {
		defineTreeModel(attrs_);
	}
	

}
	/**
	 * @return
	 */
	public TreeModel getDefaultTreeModel() {
		return _defaultTreeModel;
	}

	/**
	 * @param model
	 */
	public void setDefaultTreeModel(TreeModel model) {
		_defaultTreeModel = model;
	}

}